/*
 *  AudioFrameBufferQueue.h
 *  MantuPlay
 *
 *  Created by Markus Sintonen on 3.11.2009.
 *  Copyright 2009 __MyCompanyName__. All rights reserved.
 *
 */

#import "AudioFrameBuffer.h"

class AudioFrameBufferQueue
{
private:
	volatile unsigned int m_Read;
	volatile unsigned int m_Write;
	unsigned int m_Size;
	AudioFrameBuffer **frameBuffers;

public:
	AudioFrameBufferQueue(unsigned int buffersInQueueCount, unsigned int framesPerBuffer)
	{
		m_Read = 0;
		m_Write = 0;
		m_Size = buffersInQueueCount;
		frameBuffers = new AudioFrameBuffer *[buffersInQueueCount];
		for (unsigned int i = 0; i < buffersInQueueCount; i++) {
			AudioFrameBuffer *frameBuffer = new AudioFrameBuffer(framesPerBuffer);
			frameBuffers[i] = frameBuffer;
		}
	}
	~AudioFrameBufferQueue() 
	{
		for (unsigned int i = 0; i < m_Size; i++) {
			delete frameBuffers[i];
			frameBuffers[i] = NULL;
		}
		delete[] frameBuffers;
		frameBuffers = NULL;
	}

	//push a new element in the circular queue returns false when queue is full of if frameCount is zero
	bool PushFrameBuffer(SInt32 *frames, unsigned int frameCount)
	{
		unsigned int nextElement = (m_Write + 1) % m_Size;
		if((nextElement != m_Read) && (frameCount > 0)) 
		{
			frameBuffers[m_Write]->SetFrames(frames, frameCount);
			m_Write = nextElement;
			return true;
		}
		else
			return false;
	}
	bool ReadyToPushFrameBuffer()
	{
		unsigned int nextElement = (m_Write + 1) % m_Size;
		if(nextElement != m_Read) 
			return true;
		else
			return false;
	}

	//remove the next element from the circular queue return false if queue is empty
	bool PopFrameBuffer()
	{
		if(m_Read == m_Write)
			return false;
		
		m_Read = (m_Read + 1) % m_Size;
		return true;
	}
	
	bool NextFramesFromBuffer(SInt32 *framesDest, unsigned int count, unsigned int *outFramesCount)
	{
		if(m_Read == m_Write) {
			//Error("NextFrameFromBuffer: Queue empty!"); //Error if queue is empty
			*outFramesCount = 0;
			return false;
		}
		
		*outFramesCount = frameBuffers[m_Read]->NextFrames(framesDest, count);
		return true;
	}
};